package com.workspace.js_website.config.authentication;

import com.workspace.js_website.bean.ValidateCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 验证码过滤器
 */

@Component
public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private final List<String> smsCodeUrls = new ArrayList<>();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3000");
        response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("XDomainRequestAllowed", "1");
        //判断是否是需要校验的路径的请求
        if (smsCodeUrls.contains(request.getRequestURI())) {
            //请求验证码受否校验通过
            if (smsCodeValid(request, response)) {
                //通过则走后面的过滤器
                filterChain.doFilter(request, response);
            }
        } else {
            //非验证码拦截路径的请求直接走后面的过滤器
            filterChain.doFilter(request, response);
        }
    }

    @Override
    protected void initFilterBean() {
        //初始化拦截路径，把需要验证码校验的请求路径添加到此处
        smsCodeUrls.add("/smsLogin");
        smsCodeUrls.add("/register");
        smsCodeUrls.add("/findBackPassword");
    }

    private boolean smsCodeValid(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException, IOException {
        //判断session是否存在，不存在应该是没有发送验证码
        HttpSession session = request.getSession(false);
        if (session == null) {
            write(response, "未能找到session！");
            return false;
        }
        //获取请求中的验证码
        String smsCode = ServletRequestUtils.getStringParameter(request, "code");
        //获取请求中的手机号
        String mobile_pa = ServletRequestUtils.getStringParameter(request, "mobile");
        //获取session中的验证码
        ValidateCode validateCode = (ValidateCode) session.getAttribute("code");
        //获取session中的手机号
        String mobile_se = (String) session.getAttribute("mobile");

        if (StringUtils.isBlank(smsCode)) {
            write(response, "验证码不能为空！");
            return false;
        } else if (null == validateCode) {
            write(response, "验证码不存在！");
            return false;
        } else if (validateCode.isExpired()) {
            write(response, "验证码已过期！");
            return false;
        } else if (!StringUtils.equals(smsCode, validateCode.getCode())) {
            write(response, "验证码不正确！");
            return false;
        } else if (!Objects.equals(mobile_pa, mobile_se)) {
            write(response, "请不要修改手机号！");
            return false;
        }
        //验证通过移除session中的属性
        session.removeAttribute("code");
        session.removeAttribute("mobile");
        return true;
    }

    private void write(HttpServletResponse response, String message) throws IOException {
        //通过response返回信息
        PrintWriter writer = response.getWriter();
        writer.write("{\"data\":\"\",\"meta\":{\"status\":400,\"message\":\"" + message + "\"}}");
        writer.flush();
        writer.close();
    }
}